﻿using System;
using System.CodeDom.Compiler;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;

namespace CodeDomProviderTest
{
    class Program
    {
        static void Main(string[] args)
        {
        }

        private static void test()
        {
            //生成c#代码
            string code = GenerateCode();
            CodeDomProvider cdp = CodeDomProvider.CreateProvider("C#");

            // 编译器的参数 
            CompilerParameters cp = new CompilerParameters();
            cp.ReferencedAssemblies.Add(typeof(T).Assembly.Location);
            cp.ReferencedAssemblies.Add("System.Core.dll");//添加引用
            foreach (var ass in typeof(T).Assembly.GetReferencedAssemblies())
            {
                if (ass.Name != "System.Core")
                {
                    var refAss = AppDomain.CurrentDomain.GetAssemblies().SingleOrDefault(assembly => assembly.GetName().Name == ass.Name);
                    if (refAss != null)
                        cp.ReferencedAssemblies.Add(refAss.Location);
                }
            }
            //GenerateExecutable是设置编译后生成的是dll还是exe，true是dll，false是exe，默认是生成dll的
            cp.GenerateExecutable = false;
            //对于GenerateInMemory这个属性，MSDN上说的是true就把编译的生成的程序集保留在内存中，
            //通过CompilerResults实例的CompiledAssembly可以获取。如果设为false则是生成文件保存在磁盘上，
            //通过CompilerResults实例的PathToAssembly实例获取程序集的路径。事实是，无论GenerateInMemory设置哪个值，
            //都会在硬盘上生成相应的文件，区别在于OutputAssembly设置了相应的文件名的话，生成的文件会存在指定路径上，
            //否则会存放在系统的临时文件夹里面
            cp.GenerateInMemory = true;
            //此处如果不加，在某些情况下，默认生成的cp.TempFiles.BasePath=C:\Users\Administrator\AppData\Local\Temp\2\j2uudvfi,而不是
            //cp.TempFiles.BasePath=C:\Users\Administrator\AppData\Local\Temp\j2uudvfi,由于\2这一层级的文件夹未创建，导致抛出
            //"未能找到路径……的一部分"的异常，此处初始化一下cp.TempFiles，则可避免此问题
            cp.TempFiles = new TempFileCollection(System.IO.Path.GetTempPath());
            CompilerResults cr = cdp.CompileAssemblyFromSource(cp, code);

            //动态编译出错时
            if (cr.Errors.HasErrors)
            {
                Exception ex = new Exception();
                ex.Data["code"] = code;
                throw ex;
            }
            else
            {
                // 编译后的程序集 
                Assembly ass = cr.CompiledAssembly;
                //Namespace是命名空间，Class是类名，赋值为需要的
                Type type = ass.GetType(string.Format("{0}.{1}", Namespace, Class));
                MethodInfo objectToString = type.GetMethod("ObjectToString");
                //动态执行的方法
                structToStringExecutor = new DynamicMethodExecutor(objectToString);
            }
        }
    }
}
